<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>8. Ajax 和 http | 被删的前端游乐场</title>
    <meta name="description" content="Just playing around">
    
    
    <link rel="preload" href="/front-end-playground/assets/css/0.styles.a683ed26.css" as="style"><link rel="preload" href="/front-end-playground/assets/js/app.e5cf4092.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/3.c853767c.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/2.eed49fdd.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/36.4399717b.js" as="script">
    <link rel="stylesheet" href="/front-end-playground/assets/css/0.styles.a683ed26.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/front-end-playground/" class="home-link router-link-active"><!----> <span class="site-name">被删的前端游乐场</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端基础</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端基础</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0" style="padding-top:10px;"><div class="kitty-main" data-v-0cd75e06><span class="stand" data-v-0cd75e06></span> <div class="cat" data-v-0cd75e06><div class="body" data-v-0cd75e06></div> <div class="head" data-v-0cd75e06><div class="ear" data-v-0cd75e06></div> <div class="ear" data-v-0cd75e06></div></div> <div class="face" data-v-0cd75e06><div class="nose" data-v-0cd75e06></div> <div class="whisker-container" data-v-0cd75e06><div class="whisker" data-v-0cd75e06></div> <div class="whisker" data-v-0cd75e06></div></div> <div class="whisker-container" data-v-0cd75e06><div class="whisker" data-v-0cd75e06></div> <div class="whisker" data-v-0cd75e06></div></div></div> <div class="tail-container" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06></div></div></div></div></div></div></div></div></div></div> <p class="sidebar-heading open"><span>前端入门</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/front-end-playground/front-end-basic/front-end/front-end-1.html" class="sidebar-link">1. 什么是前端</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-2.html" class="sidebar-link">2. 编写页面</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-3.html" class="sidebar-link">3. HTML 和 CSS</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-4.html" class="sidebar-link">4. DOM 和 BOM</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-5.html" class="sidebar-link">5. Javascript</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-6.html" class="sidebar-link">6. 认识浏览器</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-7.html" class="sidebar-link">7. 代码调试</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html" class="active sidebar-link">8. Ajax 和 http</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#网络请求的发展" class="sidebar-link">网络请求的发展</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#xmlhttprequest" class="sidebar-link">XMLHttpRequest</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#理解-http-协议" class="sidebar-link">理解 HTTP 协议</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#http-与浏览器缓存" class="sidebar-link">HTTP 与浏览器缓存</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#http-与跨域" class="sidebar-link">HTTP 与跨域</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#浏览器查看请求" class="sidebar-link">浏览器查看请求</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#fiddler" class="sidebar-link">Fiddler</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#前端阶段性总结" class="sidebar-link">前端阶段性总结</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/front-end/front-end-8.html#前端杂谈" class="sidebar-link">前端杂谈</a></li></ul></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-9.html" class="sidebar-link">9. 网络协议基础</a></li><li><a href="/front-end-playground/front-end-basic/front-end/front-end-10.html" class="sidebar-link">10. 理解 HTTP 协议</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>前端深入理解</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>《前端入门》系列主要为个人对前端一些经验和认识总结。本节主要涉及 HTTP 协议和 Ajax 请求，日常开发的联调等内容。</p> <h1 id="ajax-请求"><a href="#ajax-请求" aria-hidden="true" class="header-anchor">#</a> Ajax 请求</h1> <p>Ajax 不是 JavaScript 的规范，它只是 Jesse James Garrett 提出的新术语：<code>Asynchronous JavaScript and XML</code>，意思是用 JavaScript 执行异步网络请求。</p> <h2 id="网络请求的发展"><a href="#网络请求的发展" aria-hidden="true" class="header-anchor">#</a> 网络请求的发展</h2> <p>网络请求，是用来从服务端获取需要的信息，然后解析协议和内容，来进行页面渲染或者是信息获取的过程。前面<a href="/front-end-playground/front-end-basic/front-end/front-end-6.html">《6. 认识浏览器》</a>一节已经大致说过关于浏览器渲染，以及完整的 HTTP 请求流程。</p> <p>在很久以前，我们的网络请求除了静态资源（<code>html/css/js</code>等）文件的获取，主要用于表单的提交。我们在完成表单内容的填写之后，点击<code>Submit</code>按钮，表单开始提交，浏览器就会刷新页面，然后在新页面里告诉你操作是成功了还是失败了。</p> <p>然后随着时间发展，大家觉得这样每次都刷新页面的体验太糟了，然后开始使用<code>XMLHttpRequest</code>来获取请求内容，再更新到页面中。页面开始支持局部更新、动态加载，后面还有懒加载、首屏加载等等，其实都可以算是基于这个基础吧。</p> <p>同步请求会阻塞进程，页面呈现假死状态，导致体验效果也较差。接下来，Ajax 的应用越来越广，慢慢大家都开始使用异步请求 + 回调的方式，来进行请求处理。那是一个浏览器兼容困难时期，jQuery 封装的<code>$.ajax()</code>，由于兼容性处理较好，也开始被大家广泛使用
。</p> <p>现在，我们用上了路由管理，编写单页应用，Ajax 已经是一个不可或缺的功能了。</p> <p>我们先来认识下 Ajax 的核心：<code>XMLHttpRequest</code> API 。</p> <h2 id="xmlhttprequest"><a href="#xmlhttprequest" aria-hidden="true" class="header-anchor">#</a> XMLHttpRequest</h2> <p><code>XMLHttpRequest</code>让发送一个 HTTP 请求变得非常容易。你只需要简单的创建一个请求对象实例，打开一个 URL，然后发送这个请求。当传输完毕后，结果的 HTTP 状态以及返回的响应内容也可以从请求对象中获取。</p> <p>来看个简单的例子（我们常用的 Ajax 处理）：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 新建XMLHttpRequest对象</span>

request<span class="token punctuation">.</span><span class="token function-variable function">onreadystatechange</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 状态发生变化时，函数被回调</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>request<span class="token punctuation">.</span>readyState <span class="token operator">==</span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 成功完成</span>
    <span class="token comment">// 判断响应结果:</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>request<span class="token punctuation">.</span>status <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// 成功，通过responseText拿到响应的文本</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>responseText<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      <span class="token comment">// 失败，根据响应码判断失败原因:</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>status<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// 发送请求</span>
<span class="token comment">// open的参数：</span>
<span class="token comment">// 一：请求方法，包括get/post等</span>
<span class="token comment">// 二：请求地址</span>
<span class="token comment">// 三：表示是否异步请求，若为false则是同步请求，会阻塞进程</span>
request<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token string">&quot;GET&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;/api/categories&quot;</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
request<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>大概就是上面这样，来处理一个 HTTP 请求。我们通常会将它封装成一个通用的方法，方便调用。上面例子中使用<code>200</code>来判断是否成功，但有些时候<code>200-400</code>（不包括<code>400</code>）的范围，都可以算是成功的。</p> <p>如果说我们将其封装起来，同时使用 ES6 的 Promise 的方式来操作的话，大概会是这样：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">ajax</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> method<span class="token punctuation">,</span> url<span class="token punctuation">,</span> params<span class="token punctuation">,</span> contentType <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> xhr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> formData <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>params<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">key</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    formData<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> params<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
      xhr<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>method<span class="token punctuation">,</span> url<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      xhr<span class="token punctuation">.</span><span class="token function">setRequestHeader</span><span class="token punctuation">(</span><span class="token string">&quot;Content-Type&quot;</span><span class="token punctuation">,</span> contentType<span class="token punctuation">)</span><span class="token punctuation">;</span>
      xhr<span class="token punctuation">.</span><span class="token function-variable function">onreadystatechange</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>xhr<span class="token punctuation">.</span>readyState <span class="token operator">===</span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">if</span> <span class="token punctuation">(</span>xhr<span class="token punctuation">.</span>status <span class="token operator">&gt;=</span> <span class="token number">200</span> <span class="token operator">&amp;&amp;</span> xhr<span class="token punctuation">.</span>status <span class="token operator">&lt;</span> <span class="token number">400</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// 这里我们使用200-400来判断</span>
            <span class="token function">resolve</span><span class="token punctuation">(</span>xhr<span class="token punctuation">.</span>responseText<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            <span class="token comment">// 返回请求信息</span>
            <span class="token function">reject</span><span class="token punctuation">(</span>xhr<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">;</span>
      xhr<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>formData<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">reject</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>这里使用了<code>FormData</code>来处理。通过<code>FormData</code>对象可以组装一组用<code>XMLHttpRequest</code>发送请求的键/值对。<br>
它可以更灵活方便的发送表单数据，因为可以独立于表单使用。如果你把表单的编码类型设置为<code>multipart/form-data</code>，则通过<code>FormData</code>传输的数据格式和表单通过<code>submit()</code>方法传输的数据格式相同。也支持文件的上传和添加。</p> <p>上面的代码也只是一个简单的例子，如果要封装成完善的库，我们通常还需要处理一些问题：</p> <ul><li>浏览器兼容性</li> <li>babel polyfill 处理 ES6</li> <li>get 方法通过将 params 转换拼接 URL 处理</li></ul> <p>如果想知道不使用<code>FormData</code>对象的情况下，通过 AJAX 序列化和提交表单，以及更多的<code>XMLHttpRequest</code>内容，可以参考<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest" target="_blank" rel="noopener noreferrer">Using XMLHttpRequest | MDN<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p> <h1 id="http-协议"><a href="#http-协议" aria-hidden="true" class="header-anchor">#</a> HTTP 协议</h1> <p>关于 HTTP 协议的内容，实在是太多太多，这里只大致讲一下接触比较多的。</p> <p>更多与 HTTP 协议相关的详细说明，可参考<a href="/front-end-playground/front-end-basic/front-end/front-end-10.html">《10. 理解 HTTP 协议》</a>。</p> <p>还有 TCP/IP 协议的就直接略过，可参考下<a href="/front-end-playground/front-end-basic/front-end/front-end-9.html">《9. 网络协议基础》</a>。</p> <h2 id="理解-http-协议"><a href="#理解-http-协议" aria-hidden="true" class="header-anchor">#</a> 理解 HTTP 协议</h2> <h3 id="http-结构"><a href="#http-结构" aria-hidden="true" class="header-anchor">#</a> HTTP 结构</h3> <h4 id="http-消息的结构"><a href="#http-消息的结构" aria-hidden="true" class="header-anchor">#</a> HTTP 消息的结构</h4> <ol><li>Request</li></ol> <div class="language-cmd extra-class"><pre class="language-text"><code>------------------
Request line
（包括：请求方法、请求的资源、HTTP协议的版本号）
------------------
Request header
（包括：Cache头域、Client头域、Cookie/Login头域、Entity头域、Miscellaneous头域、Transport头域等）
------------------
空行
------------------
Request body
------------------
</code></pre></div><ol start="2"><li>Response</li></ol> <div class="language-cmd extra-class"><pre class="language-text"><code>------------------
Response line
（包括：HTTP协议的版本号、状态码、消息）
------------------
Response header
（包括：Cache头域、Cookie/Login头域、Entity头域、Miscellaneous头域、Transport头域、Location头域等）
------------------
空行
------------------
Response body
------------------
</code></pre></div><h4 id="状态码"><a href="#状态码" aria-hidden="true" class="header-anchor">#</a> 状态码</h4> <p>状态码由三位数字组成，第一个数字定义了响应的类别（括号中为常见的状态码）：</p> <ul><li>1XX--提示信息：表示请求已被成功接收，继续处理</li> <li>2XX--成功：表示请求已被成功接收，理解，接受（200 OK）</li> <li>3XX--重定向：要完成请求必须进行更进一步的处理（302 Found 重定向/304 Not Modified 缓存）</li> <li>4XX--客户端错误：请求有语法错误或请求无法实现（400 Bad Request 客户端请求与语法错误/403 Forbidden 服务器拒绝提供服务/404 Not Found 请求资源不存在）</li> <li>5XX--服务器端错误：服务器未能实现合法的请求（500 Internal Server Error 服务器发生了不可预期的错误）</li></ul> <h3 id="无连接的-http"><a href="#无连接的-http" aria-hidden="true" class="header-anchor">#</a> 无连接的 HTTP</h3> <h4 id="无连接"><a href="#无连接" aria-hidden="true" class="header-anchor">#</a> 无连接</h4> <p>无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求，并收到客户的应答后，即断开连接。</p> <h4 id="keep-alive"><a href="#keep-alive" aria-hidden="true" class="header-anchor">#</a> Keep-Alive</h4> <p>Keep-Alive 功能使客户端到服务器端的连接持续有效，当出现对服务器的后继请求时，Keep-Alive 功能避免了建立或者重新建立连接。</p> <h3 id="无状态的-http"><a href="#无状态的-http" aria-hidden="true" class="header-anchor">#</a> 无状态的 HTTP</h3> <p>无状态是指协议对于事务处理没有记忆能力，服务器不知道客户端是什么状态。</p> <p>通常我们会根据场景，使用<code>Cookie</code>、<code>Token</code>、<code>Session</code>等方法来记录用户状态，完善上下请求的承接性。</p> <h2 id="http-与浏览器缓存"><a href="#http-与浏览器缓存" aria-hidden="true" class="header-anchor">#</a> HTTP 与浏览器缓存</h2> <p>浏览器会在第一次请求完服务器后得到响应，我们可以在服务器中设置这些响应，从而达到在以后的请求中尽量减少甚至不从服务器获取资源的目的。</p> <p>静态资源的缓存能减轻很多流量，如今我们的文件很多都加上了 md5，则缓存的使用越来越广泛。</p> <p>浏览器是依靠请求和响应中的的头信息来控制缓存的，主要涉及<code>Expires</code>与<code>Cache-Control</code>、<code>Last-Modified/If-Modified-Since</code>、<code>ETag/If-None-Match</code>这几个。</p> <p>第一次请求：
<img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/015343_psx2_568818.png" alt="image"></p> <p>再次请求：
<img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/015353_P04w_568818.png" alt="image"></p> <h2 id="http-与跨域"><a href="#http-与跨域" aria-hidden="true" class="header-anchor">#</a> HTTP 与跨域</h2> <h3 id="浏览器同源政策"><a href="#浏览器同源政策" aria-hidden="true" class="header-anchor">#</a> 浏览器同源政策</h3> <p>同源政策的目的，是为了保证用户信息的安全，防止恶意的网站窃取数据。所谓&quot;同源&quot;指的是&quot;三个相同&quot;: 协议相同、域名相同、端口相同。</p> <p>随着互联网的发展，&quot;同源政策&quot;越来越严格。目前，如果非同源，共有三种行为受到限制。</p> <ol><li><code>Cookie</code>、<code>LocalStorage</code>和<code>IndexDB</code>无法读取。</li> <li><code>DOM</code>无法获得。</li> <li><code>AJAX</code>请求不能发送。</li></ol> <h3 id="前端解决跨域"><a href="#前端解决跨域" aria-hidden="true" class="header-anchor">#</a> 前端解决跨域</h3> <p>跨域方法大概以下几种：</p> <ul><li><code>document.domain + iframe</code>(只有在主域相同的时候才能使用该方法)</li> <li>动态创建<code>script</code>(JSONP)</li> <li><code>location.hash + iframe</code></li> <li><code>window.name + iframe</code></li> <li><code>postMessage</code></li> <li>CORS</li> <li><code>websockets</code></li></ul> <p>现在的话，应该是 CORS 的使用会更广泛吧。实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口，就可以跨源通信。</p> <h1 id="请求联调"><a href="#请求联调" aria-hidden="true" class="header-anchor">#</a> 请求联调</h1> <p>一般来说，我们的日常联调通常有两种：浏览器查看请求，或是工具抓包查看（Fiddler）。</p> <h2 id="浏览器查看请求"><a href="#浏览器查看请求" aria-hidden="true" class="header-anchor">#</a> 浏览器查看请求</h2> <p>我们又来看浏览器的控制台了：<br> <img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/1513065617%281%29.png" alt="image"></p> <h3 id="network-面板"><a href="#network-面板" aria-hidden="true" class="header-anchor">#</a> Network 面板</h3> <p>Network 面板可以记录页面上的网络请求的详情信息，从发起网页页面请求 Request 后分析 HTTP 请求后得到的各个请求资源信息（包括状态、资源类型、大小、所用时间、Request 和 Response 等），可以根据这个进行网络性能优化。</p> <p>该面板主要包括 5 大块窗格，如图：<br> <img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/7f5c083982ec4c8378100687072118b9.png" alt="image"></p> <ul><li><strong>Controls</strong>：控制 Network 的外观和功能。</li> <li><strong>Filters</strong>：控制 Requests Table 具体显示哪些内容。</li> <li><strong>Overview</strong>：显示获取到资源的时间轴信息。</li> <li><strong>Requests Table</strong>：按资源获取的前后顺序显示所有获取到的资源信息，点击资源名可以查看该资源的详细信息。</li> <li><strong>Summary</strong>：显示总的请求数、数据传输量、加载时间信息。</li></ul> <h3 id="查看具体资源的详情"><a href="#查看具体资源的详情" aria-hidden="true" class="header-anchor">#</a> 查看具体资源的详情</h3> <p>通过点击某个资源的 Name 可以查看该资源的详细信息，根据选择的资源类型显示的信息也不太一样，可能包括如下 Tab 信息：</p> <ul><li><strong>Headers</strong>：该资源的 HTTP 头信息。</li> <li><strong>Preview</strong>：根据你所选择的资源类型（JSON、图片、文本）显示相应的预览。</li> <li><strong>Response</strong>：显示 HTTP 的 Response 信息。</li> <li><strong>Cookies</strong>：显示资源 HTTP 的 Request 和 Response 过程中的 Cookies 信息。</li> <li><strong>Timing</strong>：显示资源在整个请求生命周期过程中各部分花费的时间。</li></ul> <p>一般来说，联调主要关注请求是否正确发送、回包是否是约定的格式，所以我们更多使用资源详情的查看，包括：</p> <ul><li>查看 HTTP 头信息是否正确</li> <li>查看请求数据是否带上</li> <li>查看请求是否成功，分析 HTTP 状态码</li> <li>查看回包格式和内容是否正确</li></ul> <p>而其他功能，或许对于性能优化的时候会使用更多，先不多介绍。<br>
这里面有一篇文章写得挺详细的，可以参考<a href="http://web.jobbole.com/89106/" target="_blank" rel="noopener noreferrer">《Chrome 开发者工具详解(2)：Network 面板》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <h2 id="fiddler"><a href="#fiddler" aria-hidden="true" class="header-anchor">#</a> Fiddler</h2> <p>Fiddler 是一个 HTTP 的调试代理，以代理服务器的方式，监听系统的 Http 网络数据流动。Fiddler 可以也可以让你检查所有的 HTTP 通讯，设置断点，以及 Fiddle 所有的“进出”的数据（可用于抓包、修改请求等）。</p> <p>通常来说，我们会使用它来解决一些问题：</p> <ol><li>查看请求详情（类似上方的浏览器 Network 面板）。</li> <li>请求失败时，抓包给后台查看问题。</li> <li>模拟请求。</li> <li>拦截请求，并更改请求内容。</li> <li>移动端的请求查看和抓包。</li></ol> <p>具体的使用方式，可以参考<a href="http://www.cnblogs.com/FounderBox/p/4653588.html?utm_source=tuicool" target="_blank" rel="noopener noreferrer">Fiddler 教程<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p> <h1 id="其他深入学习"><a href="#其他深入学习" aria-hidden="true" class="header-anchor">#</a> 其他深入学习</h1> <p>就目前来说，大致的入门内容大概到这，还有很多内容或许分散在本骚年的各个系列博客中。这里放一些总结和整理相关的吧。</p> <h2 id="前端阶段性总结"><a href="#前端阶段性总结" aria-hidden="true" class="header-anchor">#</a> 前端阶段性总结</h2> <blockquote><p><a href="https://godbasin.github.io/2017/05/20/front-end-notes-7-init-http/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「理解 HTTP 协议」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> &gt; <a href="https://godbasin.github.io/2017/05/19/front-end-notes-6-network-protocol/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「网络协议基础」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <a href="https://godbasin.github.io/2017/05/14/front-end-notes-5-build-tool/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「自动化和构建工具」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <a href="https://godbasin.github.io/2017/05/12/front-end-notes-4-frame/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「框架相关」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <a href="https://godbasin.github.io/2017/05/07/front-end-notes-3-javascript-keep-moving/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「javascript 新特性」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <a href="https://godbasin.github.io/2017/05/06/front-end-notes-2-deep-into-javascript/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「深入 javascript」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <a href="https://godbasin.github.io/2017/05/01/front-end-notes-1-init-javascript/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「掌握 javascript」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <a href="https://godbasin.github.io/2017/04/30/front-end-notes-0-about/" target="_blank" rel="noopener noreferrer">《前端阶段性总结之「总览整理」》<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p></blockquote> <h2 id="前端杂谈"><a href="#前端杂谈" aria-hidden="true" class="header-anchor">#</a> 前端杂谈</h2> <blockquote><p><a href="/front-end-playground/understanding/template-engine.html">《前端模板引擎》</a><br> <a href="/front-end-playground/understanding/dialogue-abstraction.html">《对话抽象》</a><br> <a href="/front-end-playground/understanding/data-driven-or-event-driven.html">《前端思维转变--从事件驱动到数据驱动》</a><br>
还有《纯前端的进军》系列，更多可以查看 github 上博客：<a href="https://github.com/godbasin/godbasin.github.io" target="_blank" rel="noopener noreferrer">godbasin/godbasin.github.io<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p></blockquote> <h1 id="结束语"><a href="#结束语" aria-hidden="true" class="header-anchor">#</a> 结束语</h1> <p>这一节主要讲了 HTTP 请求相关，包括 Ajax（XMLHttpRequest）、HTTP 协议/跨域/缓存等，以及常用的前后台交互（联调）方式的介绍。这里面都是书面的介绍，我们需要更多的其实是实践，动手去写吧。</p></div> <!----> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/godbasin/front-end-playground/edit/sourcecode/docs/front-end-basic/front-end/front-end-8.md" target="_blank" rel="noopener noreferrer">帮阿猪改善此页面！</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <!----> <blockquote>部分文章中使用了一些网站的截图，如果涉及侵权，请告诉我删一下谢谢~</blockquote> <div style="margin-top:30px;"><div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-sm-0 el-col-md-2 el-col-lg-4" style="padding-left:10px;padding-right:10px;display:block;"><div style="width:1px;height:1px;"></div></div> <div class="el-col el-col-24 el-col-sm-24 el-col-md-18 el-col-lg-16" style="padding-left:10px;padding-right:10px;"><div class="el-card box-card is-always-shadow"><div class="el-card__header"><div class="clearfix"><span>温馨提示喵</span></div></div><div class="el-card__body"> <div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="el-image"><div class="image-slot"><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/loading.gif" style="width:100%;"></div><!----></div></div> <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="copyright-text"><div>本文版权归作者所有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</div> <div>出处：被删的前端游乐场</div> <div>作者：<a href="https://github.com/godbasin" target="_blank">被删</a></div></div></div></div></div></div></div></div></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/front-end-playground/front-end-basic/front-end/front-end-7.html" class="prev">
          7. 代码调试
        </a></span> <span class="next"><a href="/front-end-playground/front-end-basic/front-end/front-end-9.html">
          9. 网络协议基础
        </a>
        →
      </span></p></div>  <div class="gitalk-container theme-default-content"><div id="gitalk-container" class="content"></div></div></main> <div id="kitty-container"><span><div role="tooltip" id="el-popover-8129" aria-hidden="true" class="el-popover el-popper" style="width:undefinedpx;display:none;"><!----><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/2code2.jpg" class="image"> <div class="text">牡羊猪的猫粮罐</div> </div><div id="kitty" style="background:url(https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/kitty0.svg);"></div></span> <div class="el-dialog__wrapper" style="display:none;"><div role="dialog" aria-modal="true" aria-label="牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）" class="el-dialog" style="margin-top:15vh;"><div class="el-dialog__header"><span class="el-dialog__title">牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）</span><button type="button" aria-label="Close" class="el-dialog__headerbtn"><i class="el-dialog__close el-icon el-icon-close"></i></button></div><!----><!----></div></div></div></div><div class="global-ui"></div></div>
    <script src="/front-end-playground/assets/js/app.e5cf4092.js" defer></script><script src="/front-end-playground/assets/js/3.c853767c.js" defer></script><script src="/front-end-playground/assets/js/2.eed49fdd.js" defer></script><script src="/front-end-playground/assets/js/36.4399717b.js" defer></script>
  </body>
</html>
